export type IKey = string | symbol | number

export interface IObject<T = unknown> {
    [key: IKey]: T;
}
// request

export type IRequestParams<T> = T | null
// 请求路径
export type IUrl = string
// 环境判断
export type IEnv = 'Window' | 'Node'
// fetch返回取值方式
export type IDataType = "text" | "json" | "blob" | "formData" | "arrayBuffer"
// 请求方式
export type IRequestMethods = "GET" | "POST" | "DELETE" | "PUT" | "OPTIONS" | "HEAD" | "PATCH" | "TRACE" | "CONNECT"
// body结构
export type IRequestBody = IRequestParams<BodyInit>
// heads结构
export type IRequestHeaders = IRequestParams<HeadersInit>
// 请求基础函数
export type IRequestBaseFn<T = unknown> = (url: IUrl, opts: IRequestOptions) => Promise<T>
// 请求函数体
export type IRequestFn<T = unknown> = (url?: IUrl, query?: IObject<any>, body?: IRequestBody, opts?: IRequestOptions) => Promise<T>
// 请求参数
export type IRequestOptions = {
    method?: IRequestMethods
    query?: IRequestParams<IObject<any>>
    body?: IRequestBody
    headers?: IRequestHeaders
    // AbortController 中断控制器，用于中断请求
    controller?: AbortController
    // 超时时间
    timeout?: number
    // 定时器
    timer?: number | unknown | null
    [key: string]: any
} & Partial<RequestInit>
// 拦截器
export type IInterceptors = {
    // 添加请求，响应，错误拦截
    use(type: "request" | "response" | "error", fn: Function): IInterceptors
    get reqFn(): Function
    get resFn(): Function
    get errFn(): Function
}
// 公共函数
export type IRequestBase = {
    // 请求根路由
    readonly origin: string
    // 简单判断传入的路由是否是完整url
    chackUrl: (url: IUrl) => boolean
    // 环境判断，node或浏览器
    envDesc: () => IEnv
    // 全局的错误捕获
    errorFn: <Err = any, R = Function>(reject: R) => (err: Err) => R
    // 清除当前请求的超时定时器
    clearTimer: (opts: IRequestOptions) => void
    // 初始化超时取消
    initAbort: (opts: IRequestOptions) => IRequestOptions
    // 策略模式，根据环境切换请求方式
    requestType: () => IRequestBaseFn
    // 拼接请求url
    fixOrigin: (fixStr: string) => string
    // 请求函数
    fetch: IRequestBaseFn
    http: IRequestBaseFn
    // fetch响应转换方式
    getDataByType: (type: IDataType, response: Response) => Promise<any>
    // 解析http响应
    formatBodyString: (bodyString: string) => IObject<Function>
}
// 初始化并兼容传入的参数
export type IRequestInit = {
    initDefaultParams: (url: IUrl, opts: IRequestOptions) => IRequestOptions
    initFetchParams: (url: IUrl, opts: IRequestOptions) => IRequestOptions
    initHttpParams: (url: IUrl, opts: IRequestOptions) => IRequestOptions
}
// 请求主体类
export type IRequest = {
    GET: IRequestFn
    POST: IRequestFn
    DELETE: IRequestFn
    PUT: IRequestFn
    OPTIONS: IRequestFn
    HEAD: IRequestFn
    PATCH: IRequestFn
} & IRequestBase

